use anyhow::Result;
use dashmap::DashMap;
use prost::Message;
use std::collections::HashSet;
use std::net::IpAddr;
use std::sync::Arc;
use std::time::{Duration, Instant};
use tokio::net::UdpSocket;
use tokio::sync::Mutex;
use tracing::{error, info, trace, warn};

use crate::constants::WAR3_PORT;
use crate::proto::{DataForward, MessageType, War3Message};
use crate::war3_server::War3Server;

/// 本地War3游戏广播监听器
pub struct LocalWar3GameBroadcast {
    local_ip: IpAddr,
    connection_tx: Arc<tokio::sync::mpsc::UnboundedSender<War3Message>>,
    war3_servers: Arc<DashMap<String, Arc<War3Server>>>,
    my_war3_ip: Arc<Mutex<Option<String>>>,
    // 用于去重的最近数据包缓存 (data_hash, timestamp)
    recent_packets: Arc<Mutex<HashSet<(u64, Instant)>>>,
}

impl LocalWar3GameBroadcast {
    pub fn new(
        local_ip: IpAddr,
        connection_tx: Arc<tokio::sync::mpsc::UnboundedSender<War3Message>>,
        war3_servers: Arc<DashMap<String, Arc<War3Server>>>,
        my_war3_ip: Arc<Mutex<Option<String>>>,
    ) -> Self {
        Self {
            local_ip,
            connection_tx,
            war3_servers,
            my_war3_ip,
            recent_packets: Arc::new(Mutex::new(HashSet::new())),
        }
    }

    pub async fn start(self: Arc<Self>) -> Result<()> {
        loop {
            // 尝试创建并启动UDP监听器
            if let Err(e) = self.start_udp_listener().await {
                error!("LocalWar3GameBroadcast failed: {}, retrying in 1 second...", e);
                tokio::time::sleep(Duration::from_secs(1)).await;
            }
        }
    }

    async fn start_udp_listener(&self) -> Result<()> {
        // 监听本地War3游戏的UDP广播
        let bind_addr = format!("{}:{}", self.local_ip, WAR3_PORT);
        let socket = match UdpSocket::bind(&bind_addr).await {
            Ok(socket) => {
                info!("LocalWar3GameBroadcast bind success: {}", bind_addr);
                socket
            }
            Err(e) => {
                warn!("Failed to bind to {}, trying 0.0.0.0:6112: {}", bind_addr, e);
                let socket = UdpSocket::bind("0.0.0.0:6112").await?;
                info!("LocalWar3GameBroadcast bind success on 0.0.0.0:6112");
                socket
            }
        };

        let mut buf = vec![0u8; 8192];
        let recent_packets_clone = Arc::clone(&self.recent_packets);

        // 启动定期清理过期数据包缓存的任务
        tokio::spawn(async move {
            let mut interval = tokio::time::interval(Duration::from_secs(5));
            loop {
                interval.tick().await;
                let mut packets = recent_packets_clone.lock().await;
                let now = Instant::now();
                packets.retain(|(_, timestamp)| now.duration_since(*timestamp) < Duration::from_secs(2));
                if packets.len() > 1000 {
                    // 如果缓存过大，强制清理
                    packets.clear();
                }
            }
        });

        info!(
            "LocalWar3GameBroadcast started, listening on {}",
            bind_addr
        );

        loop {
            match socket.recv_from(&mut buf).await {
                Ok((len, from_addr)) => {
                    // 只处理来自本地War3游戏的UDP包
                    if from_addr.ip().to_string() == self.local_ip.to_string() {
                        info!(
                            "LocalWar3GameBroadcast received UDP from local War3: {} -> {}, {} bytes",
                            from_addr, bind_addr, len
                        );

                        // 转发UDP数据到所有远程客户端
                        let data = buf[..len].to_vec();

                        // 去重检查：计算数据包哈希
                        use std::collections::hash_map::DefaultHasher;
                        use std::hash::{Hash, Hasher};
                        let mut hasher = DefaultHasher::new();
                        data.hash(&mut hasher);
                        let data_hash = hasher.finish();
                        let now = Instant::now();

                        {
                            let mut recent_packets = self.recent_packets.lock().await;
                            
                            // 清理过期数据包
                            recent_packets.retain(|(_, timestamp)| now.duration_since(*timestamp) < Duration::from_secs(2));
                            
                            // 检查是否重复
                            if recent_packets.contains(&(data_hash, now)) {
                                info!("Duplicate packet detected, skipping forward");
                                continue;
                            }
                            
                            // 添加到缓存
                            recent_packets.insert((data_hash, now));
                        }
                        let my_war3_ip_guard = self.my_war3_ip.lock().await;
                        
                        if let Some(ref my_war3_ip) = *my_war3_ip_guard {
                            let my_ip = my_war3_ip.clone();
                            drop(my_war3_ip_guard);
                            
                            let server_count = self.war3_servers.len();
                            info!("Found {} war3 servers to forward to", server_count);
                            
                            if server_count == 0 {
                                info!("No war3 servers to forward to, skipping");
                            }

                            for war3_server_entry in self.war3_servers.iter() {
                                let other_war3_ip = war3_server_entry.key().clone();
                                let connection_tx_clone = Arc::clone(&self.connection_tx);
                                let data_clone = data.clone();
                                let my_ip_clone = my_ip.clone();

                                tokio::spawn(async move {
                                    info!("Spawning forward task: {} -> {}", my_ip_clone, other_war3_ip);
                                    if let Err(e) = Self::forward_udp_broadcast_to_server(
                                        connection_tx_clone,
                                        other_war3_ip.clone(),
                                        my_ip_clone,
                                        data_clone,
                                    )
                                    .await
                                    {
                                        error!(
                                            "Failed to forward UDP broadcast for {}: {}",
                                            other_war3_ip, e
                                        );
                                    }
                                });
                            }
                        } else {
                            info!("my_war3_ip not set yet, skipping UDP forward");
                        }
                    } else {
                        info!(
                            "LocalWar3GameBroadcast ignored UDP not from local War3: {} -> {}, {} bytes",
                            from_addr, bind_addr, len
                        );
                    }
                }
                Err(e) => {
                    error!("LocalWar3GameBroadcast receive error: {}", e);
                    // 遇到socket错误时，跳出循环让外层重新创建socket
                    return Err(e.into());
                }
            }
        }
    }

    /// 转发UDP广播到代理服务器
    async fn forward_udp_broadcast_to_server(
        connection_tx: Arc<tokio::sync::mpsc::UnboundedSender<War3Message>>,
        other_war3_ip: String,
        my_war3_ip: String,
        data: Vec<u8>,
    ) -> Result<()> {
        let data_len = data.len();

        let data_forward = DataForward {
            // from_ip: my_war3_ip.clone(),
            from_ip: other_war3_ip.clone(),
            data,
        };

        let message = War3Message {
            r#type: MessageType::DataForward as i32,
            // source_ip: my_war3_ip.clone(),
            // target_ip: other_war3_ip.clone(),
            target_ip: my_war3_ip.clone(),
            source_ip: other_war3_ip.clone(),
            payload: data_forward.encode_to_vec(),
        };

        info!(
            "LocalWar3GameBroadcast preparing to forward UDP: my_ip={} -> other_ip={} {} bytes",
            my_war3_ip, other_war3_ip, data_len
        );
        
        // 添加更多调试信息
        info!(
            "Sending DataForward message - type: DataForward, source: {}, target: {}, payload size: {}",
            message.source_ip, message.target_ip, message.payload.len()
        );

        connection_tx.send(message)?;
        info!(
            "LocalWar3GameBroadcast forwarded UDP: my_ip={} -> other_ip={} {} bytes",
            my_war3_ip, other_war3_ip, data_len
        );

        Ok(())
    }
}